home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / libraries / pchglib14.lha / SetUserCopList.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-27  |  7.4 KB  |  218 lines

  1. #include <proto/exec.h>
  2. #include <proto/graphics.h>
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <hardware/custom.h>
  6. #include <graphics/gfxmacros.h>
  7. #include <graphics/gfxbase.h>
  8. #include <graphics/copper.h>
  9. #include <intuition/screens.h>
  10. #include <iff/pchg.h>
  11. #include <clib/pchglib_protos.h>
  12.  
  13. #define min(a,b) ((a)<(b) ? (a) : (b))
  14.  
  15. #if INCLUDE_VERSION<36
  16. FAILURE!! Amiga includes version<36
  17. #endif
  18.  
  19. /* This number is hardware dependent, and limits the numbers of colors
  20. changes written by PCHG_SetUserCopList(). */
  21.  
  22. #define MAX_PER_LINE_CHANGES (15)
  23.  
  24. extern struct Custom __far custom;
  25.  
  26.  
  27. /****** pchg.lib/PCHG_SetUserCopList ****************************************
  28.  
  29.    NAME
  30.        PCHG_SetUserCopList -- Set a ViewPort Copperlist using a PCHG chunk
  31.  
  32.    SYNOPSIS
  33.        PCHG_SetUserCopList(Offset, Length, ViewPort, PCHG, LineMask, LineData);
  34.  
  35.        VOID PCHG_SetUserCopList(WORD, UWORD, struct ViewPort *,
  36.                                      struct PCHGHeader *, APTR, APTR);
  37.  
  38.    FUNCTION
  39.        Creates the Copperlist defined by a PCHG header and data. If a user
  40.        Copperlist is already defined on the ViewPort, it is first
  41.        deallocated. If Length is 0, every change specified by the PCHG
  42.        chunk will be generated. If Length is not 0, every change which
  43.        happens on a line in the range Offset<->Offset+Length will be
  44.        generated.  In each case, an offset equal to Offset is subtracted
  45.        from the PCHG indications. For instance, if Offset == 8, Length ==
  46.        10, the changes specified in the PCHG chunk for the line range 8-17
  47.        will happen on the line range 0-9. This allows setting a Copperlist
  48.        for a scrolled picture (i.e., the first displayed line is not the
  49.        first picture line). If Offset == 0, Length == ViewPort->DHeight, only
  50.        the changes which happen inside the ViewPort will be generated (with
  51.        no offset). Do NOT ask for odd offsets for a laced picture, because
  52.        of the well-known limitations of MrgCop(). Note that when Offset is
  53.        non-zero, this function will stuff via SetRGB4() all the changes which
  54.        happens before the Offset line, so that the image will be correctly
  55.        displayed. This however implies you have to reload the CMAP before each
  56.        call with an offset.
  57.  
  58.    INPUTS
  59.        Offset       - A positive offset which will be subtracted from the
  60.                       line specified by the PCHG->StartLine field.
  61.        Length       - A number of lines which will limit the
  62.                       Copperlist generation. Ignored if == 0.
  63.        ViewPort     - The ViewPort which will receive the Copperlist.
  64.        PCHG         - The PCHGHeader.
  65.        LineMask     - The line mask pointer. Technically, the LINEMASK
  66.                       part of the PCHG grammar.
  67.        LineData     - The (Small|Big)PaletteChange array
  68.                       pointer. Technically, the second part of the LINEDATA
  69.                       part of the PCHG grammar.
  70.  
  71.    RESULT
  72.        None.
  73.  
  74.    EXAMPLE
  75.  
  76.    NOTES
  77.        The MAX_PER_LINE_CHANGES #define at the start of the source
  78.        code limits the maximum number of changes allowed on a
  79.        single line. No check is done for changes on odd lines if
  80.        the ViewPort is laced. MaxReg and MinReg are ignored.
  81.        This function does *not* call RethinkDisplay() for you,
  82.        and needs graphics.library. Remember to free the user Copperlist
  83.        (if you're using a &Screen->Viewport, Intuition will do it for you).
  84.  
  85.    BUGS
  86.        Background Copperlists which a PCHGHeader->StartLine
  87.        negative value will not be correctly displayed if Offset
  88.        is not 0, because only changes on a line >=Offset will be
  89.        generated. This shouldn't be a problem however.
  90.  
  91.    SEE ALSO
  92.  
  93. *****************************************************************************/
  94.  
  95. VOID PCHG_SetUserCopList(WORD Offset, UWORD Length, struct ViewPort *ViewPort, struct PCHGHeader *PCHG, APTR LineMask, APTR LineData) {
  96.  
  97.     LONG i,j,RegNum;
  98.     ULONG r,g,b;
  99.     struct UCopList *UCop;
  100.     struct SmallLineChanges *slc;
  101.     UWORD *RGB;
  102.     ULONG *PreRGB;
  103.     struct BigLineChanges *blc;
  104.     struct BigPaletteChange *bpl;
  105.     ULONG *Mask;
  106.     BOOL Change;
  107.  
  108.     Forbid();
  109.     if (ViewPort->UCopIns) {
  110.         if (ViewPort->UCopIns->FirstCopList) FreeCopList(ViewPort->UCopIns->FirstCopList);
  111.         FreeMem(ViewPort->UCopIns, sizeof(struct UCopList));
  112.         ViewPort->UCopIns = NULL;
  113.     }
  114.     Permit();
  115.  
  116.     Mask = LineMask;
  117.     blc = (void *)(slc = LineData);
  118.  
  119.     if ((UCop = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) return;
  120.  
  121.     CINIT(UCop, PCHG->TotalChanges+PCHG->ChangedLines);
  122.  
  123.     if (Length && (PreRGB = AllocMem(sizeof(ULONG)*(PCHG->MaxReg-PCHG->MinReg+1), MEMF_PUBLIC | MEMF_CLEAR)) != NULL) {
  124.  
  125.         for(i=0; i<Offset-PCHG->StartLine; i++) {
  126.             if (Mask[i/32] & 1UL<<(31-(i%32))) {
  127.                 if (PCHG->Flags & PCHGF_12BIT) {
  128.  
  129.                     RGB = (UWORD *)&slc[1];
  130.  
  131.                     for(j=0; j<slc->ChangeCount16; j++) {
  132.                         RegNum = *RGB>>12 & 0xF;
  133.                         if (RegNum >= PCHG->MinReg && RegNum <= PCHG->MaxReg) PreRGB[RegNum-PCHG->MinReg] = 0x1000 | (*RGB & 0xFFF);
  134.                         RGB++;
  135.                     }
  136.  
  137.                     for(j=0; j<slc->ChangeCount32; j++) {
  138.                         RegNum = (*RGB>>12 & 0xF)+16;
  139.                         if (RegNum >= PCHG->MinReg && RegNum <= PCHG->MaxReg) PreRGB[RegNum-PCHG->MinReg] = 0x1000 | (*RGB & 0xFFF);
  140.                         RGB++;
  141.                     }
  142.                     slc = (void *)RGB;
  143.                 }
  144.                 else if (PCHG->Flags & PCHGF_32BIT) {
  145.  
  146.                     bpl = (void *)&blc[1];
  147.  
  148.                     for(j=0; j<blc->ChangeCount; j++) {
  149.                         if (bpl->Register >= PCHG->MinReg && bpl->Register <= PCHG->MaxReg) PreRGB[bpl->Register-PCHG->MinReg] = 0x1000000 | bpl->Red<<16 | bpl->Green<<8 | bpl->Blue;
  150.                         bpl++;
  151.                     }
  152.                     blc = (void *)bpl;
  153.                 }
  154.             }
  155.         }
  156.  
  157.         for(i=0; i<=PCHG->MaxReg-PCHG->MinReg; i++) {
  158.             if (PCHG->Flags & PCHGF_12BIT) {
  159.                 if (PreRGB[i] & 0x1000)
  160.                     SetRGB4(ViewPort, i+PCHG->MinReg, PreRGB[i]>>8 & 0xF, PreRGB[i]>>4 & 0xF, PreRGB[i] & 0xF);
  161.             }
  162.             else if (PCHG->Flags & PCHGF_32BIT) {
  163.                 if (PreRGB[i] & 0x1000000) {
  164.  
  165.                     r = PreRGB[i]>>16 & 0xFF;
  166.                     g = PreRGB[i]>>8 & 0xFF;
  167.                     b = PreRGB[i] & 0xFF;
  168.  
  169.                     if (GfxBase->LibNode.lib_Version >= 39) {
  170.                         r = r|r<<8|r<<16|r<<24;
  171.                         g = g|g<<8|g<<16|g<<24;
  172.                         b = b|b<<8|b<<16|b<<24;
  173.                         SetRGB32(ViewPort, i+PCHG->MinReg, r, g, b);
  174.                     }
  175.                     else {
  176.                         SetRGB4(ViewPort, i+PCHG->MinReg, min(r+8,0xFF)>>4, min(g+8,0xFF)>>4, min(b+8,0xFF)>>4);
  177.                     }
  178.                 }
  179.             }
  180.         }
  181.         FreeMem(PreRGB, sizeof(ULONG)*(PCHG->MaxReg-PCHG->MinReg+1));
  182.     }
  183.  
  184.     blc = (void *)(slc = LineData);
  185.  
  186.     for(i=0; i<PCHG->LineCount; i++) {
  187.         if (Mask[i/32] & 1UL<<(31-(i%32))) {
  188.             Change = (!Length || (i+PCHG->StartLine >= Offset && i+PCHG->StartLine < Offset+Length));
  189.             if (Change) CWAIT(UCop, i+PCHG->StartLine-Offset, 0);
  190.             if (PCHG->Flags & PCHGF_12BIT) {
  191.                 RGB = (UWORD *)&slc[1];
  192.                 for(j=0; j<slc->ChangeCount16; j++) {
  193.                     if (j<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[*RGB>>12 & 0xF], *RGB & 0xFFF);
  194.                     RGB++;
  195.                 }
  196.                 for(j=0; j<slc->ChangeCount32; j++) {
  197.                     if (j+slc->ChangeCount16<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[(*RGB>>12 & 0xF)+16], *RGB & 0xFFF);
  198.                     RGB++;
  199.                 }
  200.                 slc = (void *)RGB;
  201.             }
  202.             else if (PCHG->Flags & PCHGF_32BIT) {
  203.                 bpl = (void *)&blc[1];
  204.                 for(j=0; j<blc->ChangeCount; j++) {
  205.                     if (j<MAX_PER_LINE_CHANGES && Change) CMOVE(UCop, custom.color[bpl->Register], (min(bpl->Red+8, 0xFF) & 0xF0)<<4 | min(bpl->Green+8, 0xFF) & 0xF0 | min(bpl->Blue+8, 0xFF)>>4);
  206.                     bpl++;
  207.                 }
  208.                 blc = (void *)bpl;
  209.             }
  210.         }
  211.     }
  212.  
  213.     CEND(UCop);
  214.     Forbid();
  215.     ViewPort->UCopIns = UCop;
  216.     Permit();
  217. }
  218.